<?php

namespace app\api\controller;

use app\api\validate\User as UserValidate;
use app\common\controller\Frontend;
use app\common\facade\Token;
use app\logic\user\SocialiteLogic;
use app\logic\user\UserLogic;
use ba\Captcha;
use Elastic\Elasticsearch\Exception\ClientResponseException;
use Elastic\Elasticsearch\Exception\ServerResponseException;
use think\facade\Config;
use think\facade\Log;
use Throwable;

class User extends Frontend
{
    protected array $noNeedLogin = ['checkIn', 'logout', 'getAuthUrl', 'callback', 'loginWith'];

    protected array $noNeedPermission = ['index'];

    public function initialize(): void
    {
        parent::initialize();
    }

    /**
     * 会员签入(登录和注册)
     * @throws Throwable
     */
    public function checkIn(): void
    {
        // 游客接口第一次不需要验证token， 检查登录态
        if ($this->auth->isLogin() && $this->request->post('tab') == 'guestLogin') {
            $this->success(__('You have already logged in. There is no need to log in again~'), [
                'type' => $this->auth::LOGGED_IN
            ], $this->auth::LOGIN_RESPONSE_CODE);
        }

        //其他接口都要先登录游客账号
        if (!$this->auth->isLogin() && $this->request->post('tab') != 'guestLogin') {
            $this->error(__('Please login first'), [
                'type' => $this->auth::NEED_LOGIN
            ], $this->auth::LOGIN_RESPONSE_CODE);
        }

        $userLoginCaptchaSwitch = Config::get('buildadmin.user_login_captcha');
        if ($this->request->isPost()) {
            $params = $this->request->post([
                'tab', 'email', 'keep', 'captcha', 'pl', 'code', 'temp_code'
            ]);

            // 提前检查 tab ，然后将以 tab 值作为数据验证场景
            if (!in_array($params['tab'] ?? '', ['guestLogin', 'login', 'loginWith'])) {
                $this->error(__('Unknown operation'));
            }

            $validate = new UserValidate();
            try {
                $validate->scene($params['tab'])->check($params);
            } catch (Throwable $e) {
                $this->error($e->getMessage());
            }

            if ($params['tab'] == 'login') {  //邮箱登录
                $testEmail = env('testemail.email', '');
                $testEmailArr = explode(',', $testEmail);
                if (in_array($params['email'], $testEmailArr) && $params['captcha'] = 1234) {
                    // TODO 测试账号，直接登录
                } else {
                    $captchaObj = new Captcha();
                    if (!$captchaObj->check($params['captcha'], $params['email'] . 'user_login')) {
                        $this->error(__('Please enter the correct verification code'));
                    }
                }

                $res = $this->auth->login($params['email'], !empty($params['keep']));
            } elseif ($params['tab'] == 'guestLogin') {   //游客登录
                $res = $this->auth->guestLogin($params['temp_code']);
            } elseif ($params['tab'] == 'loginWith') {   //第三方登录
                $res = $this->auth->loginWith($params['pl'], $params['code']);
            }
            if (isset($res) && $res === true) {
                $this->success(__('Login succeeded!'), [
                    'userInfo' => $this->auth->getUserInfo(),
                    'routePath' => '/user'
                ]);
            } else {
                $msg = $this->auth->getError();
                if ($msg == 'need login') {
                    $this->error(__('Token expiration'), [
                        'type' => $this->auth::NEED_LOGIN
                    ], $this->auth::LOGIN_RESPONSE_CODE);
                }
                $msg = $msg ?: __('Check in failed, please try again or contact the website administrator~');
                $this->error($msg);
            }
        }

        $this->success('', [
            'userLoginCaptchaSwitch' => $userLoginCaptchaSwitch,
            'accountVerificationType' => get_account_verification_type()
        ]);
    }

    public function logout(): void
    {
        if ($this->request->isPost()) {
            $refreshToken = $this->request->post('refreshToken', '');
            if ($refreshToken) Token::delete((string)$refreshToken);
            $this->auth->logout();
            $this->success();
        }
    }


    /**
     * 第三方登录接口
     *
     * 该方法用于处理第三方登录请求，当前支持Google和Facebook作为登录方式
     * 它首先确定请求的登录类型，然后根据类型生成相应的授权URL，
     * 最后将该URL作为响应的一部分返回给客户端
     */
    public function getAuthUrl()
    {
        // 获取请求参数中的type字段，以确定登录方式
        $type = $this->request->param('type');

        // 检查请求的登录方式是否为已知并支持的方式
        $switch = config('socialite.switch');
        if (!isset($switch[$type]) || !$switch[$type]) {
            // 如果不是已知的登录方式，抛出错误提示
            $this->error(__('Unknown operation'));
        }

        $socialite = SocialiteLogic::getSocialiteManager();

        $env = $this->request->param('env');
        $socialite =$socialite->create($type);

        if (!empty($env)) {
            $socialite = $socialite->withState($env);
        }
        $url = $socialite->redirect();
        // 生成Google登录的重定向URL

        // 返回成功响应，包含重定向URL
        $this->success('', [
            'redirect_url' => $url,
        ]);
    }

    /**
     * 处理第三方平台回调的函数
     *
     * 该函数主要用于处理来自第三方社交平台的回调请求，通过请求中的平台标识和授权码，
     * 与第三方平台交换用户数据，并展示用户信息或错误信息
     */
    public function callback(): \think\response\Redirect
    {
        $state = $this->request->param('state');
        $baseUrl = match ($state){
            'local' => config('app.h5_host_dev'),
            'test' => config('app.h5_host_test'),
            default => config('app.h5_host')
        };
        $url = $baseUrl . '/?' . http_build_query($this->request->get());

        return redirect($url);
    }



    public function search()
    {
        try {
            $params = $this->request->param(['query', 'page', 'size']);


            $page = $params['page'] ? (int)$params['page'] : 1;
            $size = (int)$this->request->param('size');
            $size = $size ?: 15;

            if (config('app.env') == 'prod' && ($size > 15 || $size < 0)) {
                $size = 15;
            }
            $params['size'] = $size;
            // 计算搜索结果的起始位置
            $params['from'] = ($page - 1) * $params['size'];
            // 移除 'page' 参数，因为它已经不再需要
            unset($params['page']);

            $users = UserLogic::getInstance()->search($params, $this->auth->id);
        } catch (ClientResponseException $e) {
            $this->error($e->getMessage());
        } catch (ServerResponseException|Throwable $e) {
            $message = config('app.env') != 'prod' ? $e->getMessage() . PHP_EOL . $e->getTraceAsString() : __('Server error');
            Log::channel('my')->error($e->getMessage() . PHP_EOL . $e->getTraceAsString());
            $this->error($message);
        }

        $this->success(__("success"), $users);
    }

    /**
     * 推荐用户
     */
    public function recommend()
    {
        try {
            $users = UserLogic::getInstance()->getRecommend();
        } catch (ClientResponseException $e) {
            $this->error($e->getMessage());
        } catch (ServerResponseException|Throwable $e) {
            $this->error(__('Server error'));
        }

        $this->success(__("success"), $users);
    }
}